﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using DotNetOpenAuth.OAuth.ChannelElements;
using LinkedIn;
using LinkedIn.ServiceEntities;
using RoketSolutions.SP2010.LinkedInWebPart.Authorization;

namespace RoketSolutions.SP2010.LinkedInWebPart.Data
{
    public class LinkedInRepository
    {
        private readonly string key;
        private readonly string secret;
        private readonly ILinkedInTokenManager tokenManager;

        public LinkedInRepository(ILinkedInTokenManager tokenManager)
        {
            key = tokenManager.ConsumerKey;
            secret = tokenManager.ConsumerSecret;
            this.tokenManager = tokenManager;
        }

        public LinkedInEntity GetCurrentUser()
        {
            var tokenSource = new WebPartTokenSource(key, secret);
            var accessToken = tokenManager.GetAccessToken();
            if(accessToken != null)
            {
                var authorization = new WebOAuthAuthorization(tokenManager, accessToken.Key);
                var linkedinService = new LinkedInService(authorization);
                Person user = linkedinService.GetCurrentUser(ProfileType.Standard, InitFields());
                var entity = Wrap(user);
                return entity;
            }
            return null;
        }

        private List<ProfileField> InitFields()
        {
            var fields = new List<ProfileField>();
            /* Common */
            fields.Add(ProfileField.PersonId);
            fields.Add(ProfileField.FirstName);
            fields.Add(ProfileField.LastName);
            fields.Add(ProfileField.PublicProfileUrl);
            fields.Add(ProfileField.PictureUrl);
            fields.Add(ProfileField.Headline);
            fields.Add(ProfileField.NumberOfConnections);
            fields.Add(ProfileField.Industry);
            fields.Add(ProfileField.LocationName);
            /* Education */
            fields.Add(ProfileField.EducationActivities);
            fields.Add(ProfileField.EducationSchoolName);
            fields.Add(ProfileField.EducationDegree);
            fields.Add(ProfileField.EducationFieldOfStudy);
            fields.Add(ProfileField.EducationId);
            fields.Add(ProfileField.EducationEndDate);
            fields.Add(ProfileField.EducationStartDate);
            /* Positions */
            fields.Add(ProfileField.ThreeCurrentPositions);
            fields.Add(ProfileField.ThreePastPositions);
            fields.Add(ProfileField.PositionCompanyName);
            fields.Add(ProfileField.PositionEndDate);
            fields.Add(ProfileField.PositionId);
            fields.Add(ProfileField.PositionIsCurrent);
            fields.Add(ProfileField.PositionStartDate);
            fields.Add(ProfileField.PositionSummary);
            fields.Add(ProfileField.PositionTitle);
            return fields;
        }

        private static LinkedInEntity Wrap(Person user)
        {
            return new LinkedInEntity
            {
                ConnectionsCount = user.NumberOfConnections.ToString(),
                FirstName = user.FirstName,
                LastName = user.LastName,
                Education = GetEducation(user),
                Headline = user.Headline,
                CurrentPositions = GetCurrentPositions(user),
                ProfileId = user.Id,
                ProfilePictureUrl = user.PictureUrl,
                PublicProfileUrl = user.PublicProfileUrl,
                Industry = user.Industry,
                Location = user.Location.Name,
                Experience = GetExperience(user)
            };
        }

        private static string GetExperience(Person user)
        {
            var experience = user.Positions;
            if (experience != null && experience.Count > 0)
            {
                var exp = new List<string>();
                foreach (Position position in experience)
                {
                    if (!position.IsCurrent)
                    {
                        var startMonth = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(position.StartDate.Month);
                        var endMonth = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(position.EndDate.Month);
                        var dateStr = string.Format("{0} {1} - {2} {3}", startMonth, position.StartDate.Year, endMonth, position.EndDate.Year);
                        exp.Add(string.Format("{0} : {1} ({2})", position.Title, position.Company.Name, dateStr));
                    }
                }
                if (exp.Count > 0)
                {
                    return string.Join(",", exp.ToArray());
                }
                return null;
            }
            return null;
        }

        private static string GetCurrentPositions(Person user)
        {
            var experience = user.Positions;
            if (experience != null && experience.Count > 0)
            {
                var exp = new List<string>();
                foreach (Position position in experience)
                {
                    if (position.IsCurrent)
                    {
                        exp.Add(string.Format("{0} : {1}", position.Title, position.Company.Name));
                    }
                }
                if (exp.Count > 0)
                {
                    return string.Join(",", exp.ToArray());
                }
                return null;
            }
            return null;
        }

        private static string GetEducation(Person user)
        {
            var education = user.Educations;
            if (education != null && education.Count > 0)
            {
                return string.Join(",", education.Select(e => e.SchoolName).ToArray());
            }
            return null;
        }
    }
}
